% render "layouts/guides.html" do

All tester drivers support the common API described in this guide. By building your patterns
using this API your will be able to generate them for any ATE that is supported by Origen.

Some tester drivers may expose additional methods to leverage some key features of
the given ATE which do not have direct equivalents on other systems. You may or may not
choose to use these in your application. If you do, then be aware that you are introducing
some logic which cannot be automatically translated to other ATEs. In that case you will have to implement
the alternative implementation for other platforms on the application side,
something like this:

~~~ruby
if $tester.uflex?
  # An implementation that uses a method that only exists on the UltraFLEX driver,
  # this will make the test run more efficiently on that platform
else
  # Conventional implementation using the common API for all other platforms
end
~~~

Of course some applications may only ever wish to target a specific ATE, in that case you
can freely pick from the common and ATE-specific APIs.

This API is currently provided by the [Origen Testers plugin](http://origen-sdk.org/testers). In addition
to the primary methods discussed below, all tester drivers support the methods described in the following
API docs:

* [OrigenTesters::VectorGenerator](http://origen-sdk.org/testers/api/OrigenTesters/VectorGenerator.html)
* [OrigenTesters::Timing](http://origen-sdk.org/testers/api/OrigenTesters/Timing.html)
* [OrigenTesters::API](http://origen-sdk.org/testers/api/OrigenTesters/API.html)

### API Methods

Here are each of the main methods supported by the common API.

#### Generating Cycles

These are the basic methods for generating vectors.

##### cycle(options = {})

Generate a tester cycle or cycles:

~~~ruby
$tester.cycle
$tester.cycle repeat: 1000
~~~

As this is such a commonly used method, there are some convenience methods available, this is
equivalent to the above example:

~~~ruby
1.cycle
1000.cycles
~~~

A very common pattern when working at this level is to setup some pin states and
then trigger a cycle:

~~~ruby
pin(:tdi).drive(1)
$tester.cycle
pin(:tdi).drive(0)
$tester.cycle
~~~

All of the pin state methods support a bang (<code>!</code>) variant which will automatically
call a single cycle after setting the pin state, this is equivalent to the above:

~~~ruby
pin(:tdi).drive!(1)
pin(:tdi).drive!(0)
~~~

##### wait(options = {})

Repeats the last vector for the specified about of time. The time can be specified in cycles
or a time, multiple arguments will be added together:

~~~ruby
$tester.wait cycles: 1000         # Equivalent to $tester.cycle(repeat: 1000)
$tester.wait time_in_us: 1000     # Wait for 1000us
$tester.wait time_in_ms: 1        # Wait for 1ms

$tester.wait time_in_ms: 1, time_in_us: 1000, cycles: 100     # Wait for 2ms + 100 cycles
~~~

The wait method can also be called with additional arguments to generate a dynamic wait,
i.e. a match loop.
Here for example to wait for up to 2 seconds for the done pin to go high:

~~~ruby
$tester.wait match: true, time_in_s: 2, pin: pin(:done), state: :high
~~~

The above API is somewhat verbose, a cleaner one is available by supplying a block to generate
the vectors which much pass for the match to resolve.
This is equivalent to the previous example:

~~~ruby
$tester.wait match: true, time_in_s: 2 do
  pin(:done).assert!(1)
end
~~~

This block form also allows much more complex match conditions to be described, here to wait
for either the fail pin to go high, OR the done pin to go high:

~~~ruby
$tester.wait match: true, time_in_s: 2 do |conditions, fail|
  conditions.add do
    pin(:done).assert!(1)
  end
  conditions.add do
    pin(:fail).assert!(1)
  end
end
~~~

To AND these conditions would simply be: 

~~~ruby
$tester.wait match: true, time_in_s: 2 do
  pin(:done).assert(1)
  pin(:fail).assert(1)
  1.cycle
end
~~~

##### ignore_fails(*pins)

Ignore fails on the given pins for the duration of the given block, this
has the effect of temporarily setting the states of the given pins to
don't care.

~~~ruby
# Temporarily ignore mis-compares on the fail and data pins
$tester.ignore_fails(pin(:fail), pins(:data)) do
  # Any vectors generated in here will force the state of the given pins to X
end
~~~

#### Data Capture

##### store(*pins)

Instruct the tester to capture the data on the given pins from the vector that was generated last,
note that it does not actually generate a new vector.

Sometimes when generating vectors within a loop you may want to retrospectively capture
a previous vector, passing in an offset option will allow you to do this.

Here are some examples:

~~~ruby
$tester.cycle                        # This is the vector that we want to capture
$tester.store pin(:d0), pin(:d1)     # Capture the data on the d0 and d1 pins

$tester.cycle                        # This one gets stored
$tester.cycle
$tester.cycle
$tester.store pin(:d0), pin(:d1), offset: -2  # Just realized I need to capture that earlier vector
~~~

Note that this API is for engineers who are writing protocol drivers, most test IP would be
written at a higher level, e.g.

~~~ruby
atd_result.data.store!   # Capture the value of the ATD result bits to the tester
~~~

##### store_next_cycle(*pins)

Similar to the above, this API allows driver creators to indicate that the next vector,
wherever that may be generated, should be captured:

~~~ruby
$tester.store_next_cycle pin(:d0), pin(:d1)

# This is the vector that will be captured, in real life this could be done after returning
# to a caller
$tester.cycle  
~~~

##### capture_style

Testers support different ways of capturing vector data.  For all tester types the default
capture style is hram (history ram).  For UltraFlex digcap is additionally supported.  Change
from the default like this:

~~~ruby
# change capture style
# if the digcap isn't support for the current tester, default behavior (hram) is used
tester.capture_style = :digcap

# change back to hram capture style
tester.capture_style = :hram

# temporarily change the capture style for this cycle
tester.store_next_cycle pin(:d0), capture_style: :digcap
~~~

##### configure capture memory

Origen will create any instrument definitions required when capture memory is used.  However,
it may be desirable to alter the configuration settings.  Here is an example of how to do this:

~~~ruby
# configure TDO as a 16-bit instrument (default size is the number of pins - 1 in this case)
tester.capture_memory :digcap do |mem|
  mem.pin :tdo, size: 16
end
~~~

#### Data Source

##### overlay
Testers support different ways of modifying vector data during run time.  This practice is referred to
here as "overlay".  Overlay is requested through an optional argument to cycle:

~~~ruby
# setup overlay parameters
overlay_options = {}
# Required - what pin(s) are being overlayed?
overlay_options[:pins] = dut.pin(:tdi)
# Required - what is the overlay string? This will become a label or subroutine name
overlay_options[:overlay_str] = ovl_reg[i].overlay_str

tester.cycle overlay: overlay_options

# Generate another overlay cycle, holding the same data as the previous cycle
overlay_options[:change_data] = false
tester.cycle overlay: overlay_options

# Now a new piece of data needs to be sent
overlay_options[:change_data] = true
tester.cycle overlay: overlay_options
~~~

##### overlay_style

The default overlay style is subroutine (vectors that will be modified are replaced
by a call to a subroutine).  Change from the default like this:

~~~ruby
# if requested sytle is not available for the current tester it will default to :subroutine
tester.overlay_style = :digsrc
tester.overlay_style = :subroutine
tester.overlay_style = :label
tester.overlay_style = :handshake

# change the overlay style for this cycle only by adding :overlay_style to the overlay_options
overlay_options[:overlay_style] = :label
tester.cycle overlay: overlay_options
~~~

Not all overlay styles are supported on all testers and if the requested style is not supported a warning
will be logged and it will fall back to the default style (:subroutine).

Here is a brief summary of what each type does:

digsrc
: The vectors to be modified are updated with the data value held in a tester memory.

subroutine
: The vectors to be modified are removed from the pattern and replaced by a call to a another (subroutine) pattern.

label
: A label is inserted into the pattern immediately before the vectors to be modified.

handshake
: The vectors to be modified are removed from the pattern and replaced by a handshake with the tester.


##### configure source memory

Origen will create any necessary instruments statements.  Add configuration information to source memory
like this:

~~~ruby
tester.source_memory do |mem|
  mem.pin :tdi, size: 32, format: :binary, data_type: :long
end
~~~

#### Subroutines

##### start_subroutine(name), end_subroutine

Use these methods to write a pattern subroutine:

~~~ruby
$tester.start_subroutine "wait_for_done"
$tester.wait match: true, time_in_s: 2 do
  pin(:done).assert!(1)
end
$tester.end_subroutine
~~~

##### call_subroutine(name, options = {})

Call a pattern subroutine, an offset can be given to retrospectively jump to a subroutine
from a previous vector:

~~~ruby
$tester.call_subroutine "wait_for_done"
1.cycle
1.cycle    #  A branch will also be made after completing this vector
1.cycle
1.cycle
$tester.call_subroutine "wait_for_done", offset: -2
~~~

#### Loops and Branching

##### label(name)

Inject an arbitrary label into the pattern:

~~~ruby
$tester.label "on_failed"
~~~

##### branch_to(label)

Branch to a label:

~~~ruby
$tester.branch_to "on_failed"
~~~

##### loop_vectors(name, number_of_loops)

Execute the vectors generated within the given block *n* times:

~~~ruby
$tester.loop_vectors("my_loop", 3) do   # Do this 3 times...
  $tester.cycle
end
~~~

#### Miscellaneous

##### freq_count(pin)

Setup to measure the frequency on the given pin:

~~~ruby
$tester.freq_count pin(:clk_out)
~~~

##### microcode(code, options = {})

This can be used to inject arbitrary microcode into the pattern, which of course is
inherently coupling your logic to a specific test platform - so use sparingly!

An offset can be given to apply the microcode to previously generated vectors.

~~~ruby
$tester.microcode 'set_cpu (cpuC)'
1.cycle
1.cycle    # cpuB will be set here 
1.cycle
1.cycle
$tester.microcode 'set_cpu (cpuB)', offset: -2
~~~

##### Free-Running Clock on Existing Pin

Set up a pin to be a free-running clock with the vector generation (with respect to toggling
the pin at the appropriate intervals) automatically taken care of.

See [Pin Clock Functionality](<%= path 'guides/models/pins/#Pin_Clock_Functionality' %>) for details on the API.

% end
